home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume3 / giftops < prev    next >
Encoding:
Text File  |  1989-02-03  |  12.2 KB  |  390 lines

  1. Path: xanth!mcnc!gatech!bloom-beacon!tut.cis.ohio-state.edu!mandrill!hal!ncoast!allbery
  2. From: hemphill@cit-vax.Caltech.Edu (Scott Hemphill)
  3. Newsgroups: comp.sources.misc
  4. Subject: v03i021: GIF -> PostScript Converter
  5. Keywords: GIF,PostScript
  6. Message-ID: <6578@cit-vax.Caltech.Edu>
  7. Date: 17 May 88 19:57:06 GMT
  8. Sender: allbery@ncoast.UUCP
  9. Reply-To: hemphill@cit-vax.Caltech.Edu (Scott Hemphill)
  10. Organization: California Institute of Technology
  11. Lines: 376
  12. Approved: allbery@ncoast.UUCP
  13.  
  14. comp.sources.misc: Volume 3, Issue 21
  15. Submitted-By: "Scott Hemphill" <hemphill@cit-vax.Caltech.Edu>
  16. Archive-Name: giftops
  17.  
  18. The following program converts a GIF file to a PostScript source file.
  19. It is public domain.  It is complete in one file.  Just un-shar, and
  20. type:
  21.     cc -o giftops giftops.c
  22.  
  23. It has been tested on Sys V and BSD systems and another (non_Unix) system
  24. with 32-bit ints.  It shouldn't need more than 16-bit ints, though.
  25.  
  26. The PostScript code written by this program doesn't conform to Adobe's 
  27. standards.
  28.  
  29. Scott Hemphill    hemphill@csvax.caltech.edu    ...!ames!elroy!cit-vax!hemphill
  30.  
  31. #! /bin/sh
  32. # This is a shell archive, meaning:
  33. # 1. Remove everything above the #! /bin/sh line.
  34. # 2. Save the resulting text in a file.
  35. # 3. Execute the file with /bin/sh (not csh) to create:
  36. #    giftops.c
  37. # This archive created: Tue May 17 12:36:00 1988
  38. export PATH; PATH=/bin:/usr/bin:$PATH
  39. if test -f 'giftops.c'
  40. then
  41.     echo shar: "will not over-write existing file 'giftops.c'"
  42. else
  43. cat << \SHAR_EOF > 'giftops.c'
  44. /*********************************************
  45.  *             GIFtoPS Converter             *
  46.  *                                           *
  47.  *      May 16, 1988  by Scott Hemphill      *
  48.  *                                           *
  49.  * I wrote this program, and hereby place it *
  50.  * in the public domain, i.e. there are no   *
  51.  * copying restrictions of any kind.         *
  52.  *********************************************/
  53.  
  54. #include <stdio.h>
  55. char *malloc();
  56. int strncmp();
  57.  
  58. #define min(x,y) ((x) < (y) ? (x) : (y))
  59. #define FALSE 0
  60. #define TRUE 1
  61.  
  62. typedef int bool;
  63. typedef struct codestruct {
  64.             struct codestruct *prefix;
  65.             unsigned char first,suffix;
  66.         } codetype;
  67.  
  68. FILE *infile;
  69. unsigned int screenwidth;           /* The dimensions of the screen */
  70. unsigned int screenheight;          /*   (not those of the image)   */
  71. bool global;                        /* Is there a global color map? */
  72. int globalbits;                     /* Number of bits of global colors */
  73. unsigned char globalmap[256][3];    /* RGB values for global color map */
  74. char colortable[256][3];            /* Hex intensity strings for an image */
  75. unsigned char *raster;              /* Decoded image data */
  76. codetype *codetable;                /* LZW compression code data */
  77. int datasize,codesize,codemask;     /* Decoder working variables */
  78. int clear,eoi;                      /* Special code values */
  79.  
  80. void usage()
  81. {
  82.         fprintf(stderr,"usage: giftops input-file > output-file\n");
  83.         exit(-1);
  84. }
  85.  
  86. void fatal(s)
  87. char *s;
  88. {
  89.         fprintf(stderr,"giftops: %s\n",s);
  90.         exit(-1);
  91. }
  92.  
  93. void checksignature()
  94. {
  95.         char buf[6];
  96.  
  97.         fread(buf,1,6,infile);
  98.         if (strncmp(buf,"GIF",3)) fatal("file is not a GIF file");
  99.         if (strncmp(&buf[3],"87a",3)) fatal("unknown GIF version number");
  100. }
  101.  
  102. /* Get information which is global to all the images stored in the file */
  103.  
  104. void readscreen()
  105. {
  106.         unsigned char buf[7];
  107.  
  108.         fread(buf,1,7,infile);
  109.         screenwidth = buf[0] + (buf[1] << 8);
  110.         screenheight = buf[2] + (buf[3] << 8);
  111.         global = buf[4] & 0x80;
  112.         if (global) {
  113.             globalbits = (buf[4] & 0x07) + 1;
  114.             fread(globalmap,3,1<<globalbits,infile);
  115.         }
  116. }
  117.  
  118. /* Convert a color map (local or global) to an array of two character
  119.    hexadecimal strings, stored in colortable.  RGB is converted to
  120.    8-bit grayscale using integer arithmetic. */
  121.  
  122. void initcolors(colortable,colormap,ncolors)
  123. char colortable[256][3];
  124. unsigned char colormap[256][3];
  125. int ncolors;
  126. {
  127.         static char hextab[] = {'0','1','2','3','4','5','6','7',
  128.                                 '8','9','A','B','C','D','E','F'};
  129.         register unsigned color;
  130.         register i;
  131.  
  132.         for (i = 0; i < ncolors; i++) {
  133.             color = 77*colormap[i][0] + 150*colormap[i][1] + 29*colormap[i][2];
  134.             color >>= 8;
  135.             colortable[i][0] = hextab[color >> 4];
  136.             colortable[i][1] = hextab[color & 15];
  137.             colortable[i][2] = '\0';
  138.         }
  139. }
  140.  
  141. /* Write a postscript header to the standard output.  Standard paper size
  142.    (8.5 by 11) is hard-coded, as is the whole initialization sequence.  */
  143.  
  144. void writeheader(left,top,width,height)
  145. unsigned left,top,width,height;
  146. {
  147.         double scale;
  148.         int scaledwidth,scaledheight;
  149.  
  150.         scale = min(648.0/screenwidth, 468.0/screenheight);
  151.         scaledwidth = (int)(scale*screenwidth+0.5);
  152.         scaledheight = (int)(scale*screenheight+0.5);
  153.  
  154.         printf("currentscreen /proc exch def /angle exch def /frequency exch def\n");
  155.         printf("/angle 90 def /frequency 60 def\n");
  156.         printf("frequency angle /proc load setscreen\n");
  157.         printf("/picstr %d string def\n",width);
  158.         printf("/screen {%d %d 8 [%d 0 0 -%d 0 %d]\n",width,height,width,height,height);
  159.         printf("   {currentfile picstr readhexstring pop} image} def\n");
  160.         printf("%d %d translate 90 rotate %d %d scale screen\n",
  161.                306+(scaledheight>>1),396-(scaledwidth>>1),
  162.                scaledwidth, scaledheight);
  163. }
  164.  
  165. /* Output the bytes associated with a code to the raster array */
  166.  
  167. void outcode(p,fill)
  168. register codetype *p;
  169. register unsigned char **fill;
  170. {
  171.         if (p->prefix) outcode(p->prefix,fill);
  172.         *(*fill)++ = p->suffix;
  173. }
  174.  
  175. /* Process a compression code.  "clear" resets the code table.  Otherwise
  176.    make a new code table entry, and output the bytes associated with the
  177.    code. */
  178.  
  179. void process(code,fill)
  180. register code;
  181. unsigned char **fill;
  182. {
  183.         static avail,oldcode;
  184.         register codetype *p;
  185.  
  186.         if (code == clear) {
  187.             codesize = datasize + 1;
  188.             codemask = (1 << codesize) - 1;
  189.             avail = clear + 2;
  190.             oldcode = -1;
  191.         } else if (code < avail) {
  192.             outcode(&codetable[code],fill);
  193.             if (oldcode != -1) {
  194.                 p = &codetable[avail++];
  195.                 p->prefix = &codetable[oldcode];
  196.                 p->first = p->prefix->first;
  197.                 p->suffix = codetable[code].first;
  198.                 if ((avail & codemask) == 0 && avail < 4096) {
  199.                     codesize++;
  200.                     codemask += avail;
  201.                 }
  202.             }
  203.             oldcode = code;
  204.         } else if (code == avail && oldcode != -1) {
  205.             p = &codetable[avail++];
  206.             p->prefix = &codetable[oldcode];
  207.             p->first = p->prefix->first;
  208.             p->suffix = p->first;
  209.             outcode(p,fill);
  210.             if ((avail & codemask) == 0 && avail < 4096) {
  211.                 codesize++;
  212.                 codemask += avail;
  213.             }
  214.             oldcode = code;
  215.         } else {
  216.             fatal("illegal code in raster data");
  217.         }
  218. }
  219.  
  220. /* Decode a raster image */
  221.  
  222. void readraster(width,height)
  223. unsigned width,height;
  224. {
  225.         unsigned char *fill = raster;
  226.         unsigned char buf[255];
  227.         register bits=0;
  228.         register unsigned count,datum=0;
  229.         register unsigned char *ch;
  230.         register int code;
  231.  
  232.         datasize = getc(infile);
  233.         clear = 1 << datasize;
  234.         eoi = clear+1;
  235.         codesize = datasize + 1;
  236.         codemask = (1 << codesize) - 1;
  237.         codetable = (codetype*)malloc(4096*sizeof(codetype));
  238.         if (!codetable) fatal("not enough memory for code table");
  239.         for (code = 0; code < clear; code++) {
  240.             codetable[code].prefix = (codetype*)0;
  241.             codetable[code].first = code;
  242.             codetable[code].suffix = code;
  243.         }
  244.         for (count = getc(infile); count > 0; count = getc(infile)) {
  245.             fread(buf,1,count,infile);
  246.             for (ch=buf; count-- > 0; ch++) {
  247.                 datum += *ch << bits;
  248.                 bits += 8;
  249.                 while (bits >= codesize) {
  250.                     code = datum & codemask;
  251.                     datum >>= codesize;
  252.                     bits -= codesize;
  253.                     if (code == eoi) goto exitloop;  /* This kludge put in
  254.                                                         because some GIF files
  255.                                                         aren't standard */
  256.                     process(code,&fill);
  257.                 }
  258.             }
  259.         }
  260. exitloop:
  261.         if (fill != raster + width*height) fatal("raster has the wrong size");
  262.         free(codetable);
  263. }
  264.  
  265. /* Read a row out of the raster image and write it to the output file */
  266.  
  267. void rasterize(row,width)
  268. int row,width;
  269. {
  270.         register unsigned char *scanline;
  271.         register i;
  272.  
  273.         scanline = raster + row*width;
  274.         for (i = 0; i < width; i++) {
  275.             if (i % 40 == 0) printf("\n");  /* break line every 80 chars */
  276.             fputs(colortable[*scanline++],stdout);
  277.         }
  278.         printf("\n");
  279. }
  280.  
  281. /* write image trailer to standard output */
  282.  
  283. void writetrailer()
  284. {
  285.         printf("showpage\n");
  286. }
  287.  
  288. /* Read image information (position, size, local color map, etc.) and convert
  289.    to postscript. */
  290.  
  291. void readimage()
  292. {
  293.         unsigned char buf[9];
  294.         unsigned left,top,width,height;
  295.         bool local,interleaved;
  296.         char localmap[256][3];
  297.         int localbits;
  298.         int *interleavetable;
  299.         register row;
  300.         register i;
  301.  
  302.         fread(buf,1,9,infile);
  303.         left = buf[0] + (buf[1] << 8);
  304.         top = buf[2] + (buf[3] << 8);
  305.         width = buf[4] + (buf[5] << 8);
  306.         height = buf[6] + (buf[7] << 8);
  307.         local = buf[8] & 0x80;
  308.         interleaved = buf[8] & 0x40;
  309.         if (local) {
  310.             localbits = (buf[8] & 0x7) + 1;
  311.             fread(localmap,3,1<<localbits,infile);
  312.             initcolors(colortable,localmap,1<<localbits);
  313.         } else if (global) {
  314.             initcolors(colortable,globalmap,1<<globalbits);
  315.         } else {
  316.             fatal("no colormap present for image");
  317.         }
  318.         writeheader(left,top,width,height);
  319.         raster = (unsigned char*)malloc(width*height);
  320.         if (!raster) fatal("not enough memory for image");
  321.         readraster(width,height);
  322.         if (interleaved) {
  323.             interleavetable = (int*)malloc(height*sizeof(int));
  324.             if (!interleavetable) fatal("not enough memory for interleave table");
  325.             row = 0;
  326.             for (i = top; i < top+height; i += 8) interleavetable[i] = row++;
  327.             for (i = top+4; i < top+height; i += 8) interleavetable[i] = row++;
  328.             for (i = top+2; i < top+height; i += 4) interleavetable[i] = row++;
  329.             for (i = top+1; i < top+height; i += 2) interleavetable[i] = row++;
  330.             for (row = top; row < top+height; row++) rasterize(interleavetable[row],width);
  331.             free(interleavetable);
  332.         } else {
  333.             for (row = top; row < top+height; row++) rasterize(row,width);
  334.         }
  335.         free(raster);
  336.         writetrailer();
  337. }
  338.  
  339. /* Read a GIF extension block (and do nothing with it). */
  340.  
  341. void readextension()
  342. {
  343.         unsigned char code,count;
  344.         char buf[255];
  345.  
  346.         code = getc(infile);
  347.         while (count = getc(infile)) fread(buf,1,count,infile);
  348. }
  349.  
  350. main(argc,argv)
  351. int argc;
  352. char *argv[];
  353. {
  354.         int quit = FALSE;
  355.         char ch;
  356.  
  357.         if (argc != 2) usage();
  358.         infile = fopen(argv[1],"r");
  359.         if (!infile) {
  360.             perror("giftops");
  361.             exit(-1);
  362.         }
  363.         checksignature();
  364.         readscreen();
  365.         do {
  366.             ch = getc(infile);
  367.             switch (ch) {
  368.                 case '\0':  break;  /* this kludge for non-standard files */
  369.                 case ',':   readimage();
  370.                             break;
  371.                 case ';':   quit = TRUE;
  372.                             break;
  373.                 case '!':   readextension();
  374.                             break;
  375.                 default:    fatal("illegal GIF block type");
  376.                             break;
  377.             }
  378.         } while (!quit);
  379. }
  380. SHAR_EOF
  381. if test 10781 -ne "`wc -c < 'giftops.c'`"
  382. then
  383.     echo shar: "error transmitting 'giftops.c'" '(should have been 10781 characters)'
  384. fi
  385. fi
  386. exit 0
  387. #    End of shell archive
  388. -- 
  389. Scott Hemphill    hemphill@csvax.caltech.edu    ...!ames!elroy!cit-vax!hemphill
  390.